From: kaf24@firebug.cl.cam.ac.uk Date: Fri, 5 May 2006 13:05:31 +0000 (+0100) Subject: Fix injection of guest faults resulting from failed injection of a X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16108^2~10^2~2 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=31d6525e2b44278042855e4e352b3d7504591cac;p=xen.git Fix injection of guest faults resulting from failed injection of a previous event. We enter an infinite loop if the original failed injection cannot be fixed up by Xen (e.g., because it's not a shadow pagetable issue). The RHEL4 HVM guest hang issue was actually a side effect of change-set 9699. In the rhel4 guest hang rc.sysinit init-script was calls kmodule program to probe the hardware. The kmodule uses the kudzu library call probeDevices(). For probing the graphics hardware in the vbe_get_mode_info() function, sets up the environment and goes into the vm86 mode to do the int x10 call. For returning back to protected mode it sets up a int 0xff call. At the time of calling the int 0xff the guest process pages were not filled up. And it was causing an infinite loop of vmexits with the IDT_VECTORING_INFO on the int 0xff instruction. The reason for the infinite loop is changeset 9699. With that the guest page fault was always getting overridden by the int 0xff gp fault coming from the IDT_VECTORING_INFO. With the attached patch if VMM is injecting exceptions like page faults or gp faults then IDT_VECTORING_INFO field does not override it, and that breaks the vmexit infinite loop for the rhel4. Signed-off-by: Nitin A Kamble Signed-off-by: Jun Nakajima Signed-off-by: Edwin Zhai --- diff --git a/xen/arch/x86/hvm/vmx/io.c b/xen/arch/x86/hvm/vmx/io.c index 9835445d61..f2199cbcb1 100644 --- a/xen/arch/x86/hvm/vmx/io.c +++ b/xen/arch/x86/hvm/vmx/io.c @@ -166,20 +166,26 @@ asmlinkage void vmx_intr_assist(void) } has_ext_irq = cpu_has_pending_irq(v); + + if (unlikely(v->arch.hvm_vmx.vector_injected)) { + v->arch.hvm_vmx.vector_injected=0; + if (unlikely(has_ext_irq)) enable_irq_window(v); + return; + } + __vmread(IDT_VECTORING_INFO_FIELD, &idtv_info_field); - if (idtv_info_field & INTR_INFO_VALID_MASK) { + if (unlikely(idtv_info_field & INTR_INFO_VALID_MASK)) { __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field); __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len); - if (inst_len >= 1 && inst_len <= 15) - __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len); + __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len); - if (idtv_info_field & 0x800) { /* valid error code */ + if (unlikely(idtv_info_field & 0x800)) { /* valid error code */ unsigned long error_code; __vmread(IDT_VECTORING_ERROR_CODE, &error_code); __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); } - if ( has_ext_irq ) + if (unlikely(has_ext_irq)) enable_irq_window(v); HVM_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field); @@ -187,8 +193,9 @@ asmlinkage void vmx_intr_assist(void) return; } - if ( !has_ext_irq ) return; - if ( is_interruptibility_state() ) { /* pre-cleared for emulated instruction */ + if (likely(!has_ext_irq)) return; + + if (unlikely(is_interruptibility_state())) { /* pre-cleared for emulated instruction */ enable_irq_window(v); HVM_DBG_LOG(DBG_LEVEL_1, "interruptibility"); return; diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h index b2545bbd26..c4f1c70745 100644 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -68,6 +68,7 @@ struct arch_vmx_struct { struct vmcs_struct *vmcs; /* VMCS pointer in virtual. */ unsigned int launch_cpu; /* VMCS is valid on this CPU. */ u32 exec_control; /* cache of cpu execution control */ + u32 vector_injected; /* if there is vector installed in the INTR_INFO_FIELD */ unsigned long flags; /* VMCS flags */ unsigned long cpu_cr0; /* copy of guest CR0 */ unsigned long cpu_shadow_cr0; /* copy of guest read shadow CR0 */ diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h index 864b393e9d..26d497f8a6 100644 --- a/xen/include/asm-x86/hvm/vmx/vmx.h +++ b/xen/include/asm-x86/hvm/vmx/vmx.h @@ -444,6 +444,7 @@ static inline int __vmx_inject_exception(struct vcpu *v, int trap, int type, static inline int vmx_inject_exception(struct vcpu *v, int trap, int error_code) { + v->arch.hvm_vmx.vector_injected = 1; return __vmx_inject_exception(v, trap, INTR_TYPE_EXCEPTION, error_code); }